package org.dormi.learn.definition;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

/**
 * @author : dormi330
 * @since : 2021/1/27/0027
 * 顶点
 */
public class Vertex {
    public static final int SEQ_NOT_SET = -1;
    public static final int DEFAULT_DEGREE = 0;
    private static final Logger log = LoggerFactory.getLogger(Vertex.class);
    public final String id;

    /**
     * 入度和出度, 在图中才有意义
     */
    private int inDegree = DEFAULT_DEGREE;
    private int outDegree = DEFAULT_DEGREE;

    /**
     * Arrival Time is the time at which the vertex was explored for the first time in the DFS
     * Departure Time is the time at which we have explored all the neighbors of the vertex and we are ready to backtrack
     */
    private int departure = SEQ_NOT_SET;
    private int arrival = SEQ_NOT_SET;

    public Vertex(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return String.format("V[%s]", id);
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }

    @Override
    public boolean equals(Object other) {
        if (other == null) {
            return false;
        }

        if (!(other instanceof Vertex)) {
            return false;
        }

        Vertex v2 = (Vertex) other;
        if (Objects.equals(id, v2.id)) {
            return true;
        }

        return false;
    }

    public int getArrival() {
        return arrival;
    }

    public int getDeparture() {
        return departure;
    }

    public int arrival(int seq) {
        if (this.arrival == SEQ_NOT_SET) {
            log.debug("arrival [uid={}, {} -> {}]", id, this.arrival, seq);
            this.arrival = seq;
        }
        return this.arrival;
    }

    public int departure(int seq) {
        if (this.departure == SEQ_NOT_SET) {
            log.debug("departure [uid={}, {} -> {}]", id, this.departure, seq);
            this.departure = seq;
        }
        return this.departure;
    }

    public int incInDegree() {
        inDegree++;
        return inDegree;
    }

    public int incOutDegree() {
        outDegree++;
        return outDegree;
    }

    public int getInDegree() {
        return inDegree;
    }

    public void setInDegree(int inDegree) {
        this.inDegree = inDegree;
    }

    public void setOutDegree(int outDegree) {
        this.outDegree = outDegree;
    }

    public int getOutDegree() {
        return outDegree;
    }
}
